<template>
	<e-picker :show="props.show" ref="pickerRef" keyName="label" :columns="innerColumns"
		:showToolbar="props.showToolbar" :visibleItemCount="props.visibleItemCount"
		:closeOnClickOverlay="props.closeOnClickOverlay" :defaultIndex="props.defaultIndex"
		:itemHeight="props.itemHeight" :loading="loading" :immediateChange="props.immediateChange" @close="handleClose"
		@change="changeHandler" @confirm="handleConfirm">
		<template #toolbar>
			<slot name="toolbar">
				<toolbar  :show="props.showToolbar" :title="props.title" :cancelColor="props.cancelColor" :confirmColor="props.confirmColor"
					:cancelText="props.cancelText" :confirmText="props.confirmText" @cancel="cancel" @confirm="confirm">
				</toolbar>
			</slot>
		</template>
		<template #footer>
			<slot name="footer">
			</slot>
		</template>
	</e-picker>
</template>
<script lang="ts">
	import {
		defineComponent
	} from 'vue'
	import mpMixin from '../../libs/mixin/mpMixin'
	/**
	 * e-lazy-picker
	 * @description 选择器
	 * @property {Boolean}			show				是否显示picker弹窗（默认 false ）
	 * @property {Boolean}			showToolbar			是否显示顶部的操作栏（默认 true ）
	 * @property {Array}			option				可选项数据源
	 * @property {String | Number}	itemHeight			各列中，单个选项的高度（默认 44 ）
	 * @property {String}			title				顶部标题
	 * @property {String}			cancelText			取消按钮的文字（默认 '取消' ）
	 * @property {String}			confirmText			确认按钮的文字（默认 '确定' ）
	 * @property {String}			cancelColor			取消按钮的颜色（默认 '#909193' ）
	 * @property {String}			confirmColor		确认按钮的颜色（默认 '#3c9cff' ）
	 * @property {String | Number}	visibleItemCount	每列中可见选项的数量（默认 5 ）
	 * @property {Boolean}			closeOnClickOverlay	是否允许点击遮罩关闭选择器（默认 false ）
	 * @property {Array}			defaultIndex		各列的默认索引
	 * @property {Boolean}			immediateChange		是否在手指松开时立即触发change事件（默认 false ）
	 * @event {Function} close		关闭选择器时触发
	 * @event {Function} cancel		点击取消按钮触发
	 * @event {Function} change		当选择值变化时触发
	 * @event {Function} confirm	点击确定按钮，返回当前选择的值
	 */
	export default defineComponent({
		name: 'e-lazy-picker',
		mixins: [mpMixin]
	})
</script>
<script lang="ts" setup>
	import {
		ref,
		nextTick,
		toRefs,
		onMounted
	} from 'vue'
	import {
		lazyPickerProps,
		lazyPickerEmits
	} from './props';
	import {
		empty,
		isArray
	} from '../../libs/utils'
	import {
		useDefaultProps
	} from '../../libs/hooks'
	import {
		useLazyLoadConfig,
		Store,
		Node,
		type ELazyPickerContext,
		type LazyPickerOption
	} from './util'
	import type {
		PickerContext
	} from '../../libs/tokens'
	import componentsProps, {
		type DefaultProps
	} from "../../libs/config/componentsProps";
	import toolbar from '../toolbar/index.vue'

	const {
		lazyPicker: lazyPickerDefaultProps
	} = toRefs(componentsProps);

	const _props = defineProps(lazyPickerProps)

	const props = useDefaultProps < DefaultProps['lazyPicker'] > (_props, lazyPickerDefaultProps);
	const emit = defineEmits(lazyPickerEmits)

	const {
		config
	} = useLazyLoadConfig({
		props: props.value.props
	})

	let store: Store | null = null

	const loading = ref(false)
	const pickerRef = ref < PickerContext|null > (null)

	// 各列的值
	const innerColumns = ref < Array < Node[] > > ([])


	const lazyLoad: ELazyPickerContext['lazyLoad'] = (node, cb) => {
		const cfg = config.value;
		node = node || new Node({}, cfg, undefined, true);
		node.loading = true
		loading.value = true
		const resolve = (dataList: LazyPickerOption[]) => {
			const _node = node as Node
			const parent = _node.root ? null : _node
			dataList && store?.appendNodes(dataList, parent as any)
			loading.value = false
			_node.loading = false
			_node.loaded = true
			_node.childrenData = _node.childrenData || []
			cb && cb(dataList)


		}

		cfg.lazyLoad(node, resolve as any)
	}


	const initStore = () => {
		const cfg = config.value
		cfg.lazy = true
		const cb = (list: any[]) => {
			store = new Store(list, cfg)
			pickerRef.value?.setColumnValues(0, store.getNodes())
			const columnValues = pickerRef.value?.getColumnValues(0)||[]
			columnValues.length && setColumnValue(columnValues[0], 1, true)
		}
		if (props.value.props.lazy&&empty(props.value.option)) {
			lazyLoad(undefined, (list) => {
				if (isArray(list) && list.length) {
					cb(list)
				}
			})
		} else {
			nextTick(() => {
				cb(isArray(props.value.option) ? props.value.option : [])
			})

		}
	}

	const setColumnValue = (node: Node, index: number, isResetIndex ? : boolean) => {
		const cb = () => {
			if (node.children.length) {
				pickerRef.value?.setColumnValues(index, node.children)
				setColumnValue(node.children[0], index + 1, isResetIndex)
			} else {
				// 初始化picker的索引
				isResetIndex && pickerRef.value?.setIndexs(new Array(index).fill(0), true)
			}
		}
		if (!props.value.props.lazy||node.loaded) {
			cb()
		} else {
			lazyLoad(node, (list) => {
				if (isArray(list) && list.length) {
					cb()
				} else {
					// 初始化picker的索引
					isResetIndex && pickerRef.value?.setIndexs(new Array(index).fill(0), true)
				}
			})
		}

	}


	// 关闭选择器
	const handleClose = () => {
		if (props.value.closeOnClickOverlay) {
			emit('close')
		}
	}
	// 点击工具栏的取消按钮
	const cancel = () => {
		emit('cancel')
	}
	// 点击工具栏的确定按钮
	const confirm = () => {
		pickerRef.value?.confirm()
	}

	const handleConfirm = (e: {
		indexs: number[],
		value: Node[],
		values: Array < Node[] > ,
	}) => {

		emit('confirm', {
			indexs: e.indexs,
			value: e.value.map(item => item.data),
			values: e.values
		})
	}
	// 选择器某一列的数据发生变化时触发
	const changeHandler = (e: {
		index: number,
		indexs: number[],
		value: Node[],
		values: Array < Node[] > ,
		columnIndex: number
	}) => {
		let {
			index,
			indexs,
			value,
			values,
			columnIndex
		} = e
		const node = e.value[columnIndex]
		node && setColumnValue(node, columnIndex + 1)


		emit('change', {
			index,
			indexs,
			value: value.map(item => item.data),
			values,
			columnIndex
		})
	}
	
	onMounted(() => {
		initStore()
	})

	defineExpose({
		confirm
	})
</script>

<style lang="scss" scoped>

</style>
